# coding=utf-8
from hbase import Hbase
from hbase.ttypes import Mutation
from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol

import Eblob.setting

from BaseObj import BaseObj


class ThriftConnection(Hbase.Client):
    def __init__(self):
        self.transport = TSocket.TSocket(Eblob.setting.host, Eblob.setting.port)
        self.protocol = TBinaryProtocol.TBinaryProtocol(self.transport)
        Hbase.Client.__init__(self, iprot=self.protocol, oprot=None)
        self.transport.open()

    def get_tables(self):
        return self.getTableNames()

    def close_connection(self):
        self.transport.close()

    def _is_existed(self, table_name, row_key, is_like=False):
        if Eblob.setting.real_delete:
            if is_like:
                scan_filter = "RowFilter(=,'regexstring:" + row_key + "')"
                scan = Hbase.TScan()
                scan.filterString = scan_filter
                results = self.scannerGetList(self.scannerOpenWithScan(
                    tableName=table_name, scan=scan, attributes=None), 1)
                return len(results) > 1
            else:
                result = self.getRow(table_name, row_key, None)
                return len(result) != 0
        else:
            if is_like:
                scan_filter = "RowFilter(=,'regexstring:" + row_key + "')"
                scan = Hbase.TScan()
                scan.filterString = scan_filter
                results = self.scannerGetList(self.scannerOpenWithScan(
                    tableName=table_name, scan=scan, attributes=None), 1)
                is_existed = False
                for result in results:
                    if result.columns['status:status'].value == '1':
                        is_existed = True
                        break
                return is_existed
            else:
                result = self.getRow(table_name, row_key, None)
                return result[0].columns['status:status'].value == '1'

    def _save(self, table_name, row_key, maps):
        mutations = list()
        for name in maps.keys():
            mutations.append(Mutation(column=name, value=maps.get(name)))
        mutations.append(Mutation(column="status:status", value='1'))
        self.mutateRow(table_name, row_key, mutations, None)

    def _find(self, table_name, row_key_like, start_row, counts):
        scan_filter = "RowFilter(=,'regexstring:" + row_key_like + "')"
        scan = Hbase.TScan()
        if start_row != '0':
            scan.startRow = start_row
        scan.filterString = scan_filter
        results = self.scannerGetList(self.scannerOpenWithScan(
            tableName=table_name, scan=scan, attributes=None), counts)
        if Eblob.setting.real_delete:
            return results
        else:
            final_results = list()
            for result in results:
                if result.columns['status:status'].value == '1':
                    final_results.append(result)
            return final_results

    def _get_one(self, table_name, row_key):
        obj = self.getRow(table_name, row_key, None)
        if Eblob.setting.real_delete:
            return obj
        else:
            if obj[0].columns['status:status'].value == '1':
                return obj
            else:
                return []

    def _delete(self, table_name, row_key):
        if Eblob.setting.real_delete:
            self.deleteAllRow(table_name, row_key, None)
        else:
            mutations = list()
            mutations.append(Mutation(column="status:status", value='0'))
            self.mutateRow(table_name, row_key, mutations, None)

    def real_is_existed(self, table_name, row_key, is_like=False):
        return self._is_existed(table_name, row_key, is_like)

    def real_save(self, table_name, row_key, maps):
        self._save(table_name, row_key, maps)

    def real_find(self, table_name, row_key_like, start_row, counts):
        objs = list()
        results = self._find(table_name, row_key_like, start_row, counts)
        for result in results:
            obj = BaseObj()
            obj['row_key'] = result.row
            for element_name in result.columns.keys():
                print element_name
                obj[element_name] = result.columns[element_name].value
            objs.append(obj)
        return objs

    def real_get(self, table_name, row_key):
        results = self._get_one(table_name, row_key)
        if len(results) == 0:
            return None
        else:
            result = results[0]
            obj = BaseObj()
            obj['row_key'] = result.row
            for element_name in result.columns.keys():
                obj[element_name] = result.columns[element_name].value
            return obj

    def real_delete(self, table_name, row_key):
        self._delete(table_name, row_key)

    def real_delete_like(self, table_name, row_key_like):
        while True:
            results = self.real_find(table_name, row_key_like, '0', 1000)
            for result in results:
                self.real_delete(table_name, result.row)
            if len(results) < 1000:
                break
